﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.IO;
using System.Xml;
using Microsoft.SystemCenter.Orchestrator.Integration;

namespace Inframon.IntegrationPack.WindowsAzure
{
    [Activity("Create SQL Server")]
    public class CreateSqlServer : IActivity
    {
        [ActivityConfiguration(Usage = ConfigurationUsage.DesignAndExecute), ActivityOutput]
        public AzureSettings Settings { get; set; }

        public void Design(IActivityDesigner designer)
        {
            // Define activity inputs
            designer.AddInput("Location");
            designer.AddInput("Admin Username");
            designer.AddInput("Admin Password");

            // Define activity outputs
            designer.AddOutput("MS Request ID");
            designer.AddOutput("Status Code");
            designer.AddOutput("Server Name");

            // Define error outputs
            designer.AddOutput("HTTP Code");
            designer.AddOutput("Exception");
            designer.AddOutput("Stack Trace");
        }

        public void Execute(IActivityRequest request, IActivityResponse response)
        {
            try
            {
                string url = string.Format("https://management.database.windows.net:8443/{0}/servers", Settings.SubscriptionId);
                HttpWebRequest webRequest = HttpWebRequest.Create(url) as HttpWebRequest;

                webRequest.ClientCertificates.Add(new X509Certificate2(Settings.PfxFilePath, Settings.PfxPassword));
                webRequest.Headers["x-ms-version"] = "1.0";
                webRequest.Method = "POST";

                string xmlBody = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
                                 "<Server xmlns=\"http://schemas.microsoft.com/sqlazure/2010/12/\">\n" +
                                 "  <AdministratorLogin>" + request.Inputs["Admin Username"].ToString() + "</AdministratorLogin>\n" +
                                 "  <AdministratorLoginPassword>" + request.Inputs["Admin Password"].ToString() + "</AdministratorLoginPassword>\n" +
                                 "  <Location>" + request.Inputs["Location"].ToString() + "</Location>\n" +
                                 "</Server>";

                byte[] bytes = Encoding.UTF8.GetBytes(xmlBody);
                webRequest.ContentLength = bytes.Length;
                webRequest.ContentType = "application/xml;charset=utf-8";
                using (Stream requestStream = webRequest.GetRequestStream())
                {
                    requestStream.Write(bytes, 0, bytes.Length);
                }

                using (WebResponse webResponse = webRequest.GetResponse())
                {

                    //=== x-ms-request-id is useful for troubleshooting request failures with Microsoft ===//
                    response.Publish("MS Request ID", webResponse.Headers["x-ms-request-id"]);
                    response.Publish("Status Code", (int)((HttpWebResponse)webResponse).StatusCode);

                    using (Stream stream = webResponse.GetResponseStream())
                    {
                        using (XmlTextReader xmlReader = new XmlTextReader(stream))
                        {
                            while (xmlReader.Read())
                            {
                                switch (xmlReader.NodeType)
                                {
                                    case XmlNodeType.Element:
                                        if (xmlReader.Name == "ServerName")
                                        {
                                            if (xmlReader.Read() && (xmlReader.NodeType == XmlNodeType.Text))
                                            {
                                                // Publish server name of new server
                                                response.Publish("Server Name", xmlReader.Value.ToString());
                                            }
                                        }
                                        break;
                                }
                            }
                        }
                    }
                }
            }
            catch (WebException webEx)
            {
                // Write exception to output
                response.Publish("Exception", webEx.ToString());

                try
                {
                    HttpWebResponse errorResponse = (HttpWebResponse)webEx.Response;

                    // Write HTTP error code
                    response.Publish("HTTP Code", (int)errorResponse.StatusCode);

                    using (Stream errorResponseStream = errorResponse.GetResponseStream())
                    {
                        using (StreamReader sr = new StreamReader(errorResponseStream))
                        {
                            ////Console.WriteLine(sr.ReadToEnd());
                        }
                    }
                }
                catch (Exception innerEx)
                {
                    response.Publish("Exception", innerEx.ToString());
                    response.Publish("Stack Trace", innerEx.StackTrace.ToString());
                }
            }
            catch (Exception ex)
            {
                // Report error event
                response.ReportErrorEvent(ex.Message, ex.StackTrace);
            }
        }
    }
}